import { getFileContentAndPath } from '../../../bin/frameworks/filesystem/getFileContentAndPath';

import {
  getFileContentAndPathOperationToken,
  getFileContentAndPathOperationComponent,
  getFileContentAndPathOperationStyle,
  getFileContentAndPathOperationCss,
  getFileContentAndPathOperationStory,
  getFileContentAndPathOperationDescription,
  expectedEnum,
  expectedStandard,
  expectedTs,
  expectedCss,
  expectedScss
} from '../../../testdata/getFileContentAndPathOperation';

import {
  ErrorGetFileContentAndPath,
  ErrorGetFileContentAndPathMissingFields,
  ErrorGetFileContentAndPathNoReturn
} from '../../../bin/frameworks/errors/errors';

describe('Failure cases', () => {
  test('It should throw an error if running without arguments', () => {
    // @ts-ignore
    expect(() => getFileContentAndPath()).toThrowError(ErrorGetFileContentAndPath);
  });

  test('It should throw an error if missing any fields', () => {
    // @ts-ignore
    expect(() => getFileContentAndPath({})).toThrowError(ErrorGetFileContentAndPathMissingFields);
  });

  test('It should throw an error if it cannot resolve a valid type', () => {
    const invalidContentType = {
      type: 1,
      file: 1,
      path: 1,
      name: 1,
      format: 1,
      element: 1
    };

    expect(() =>
      // @ts-ignore
      getFileContentAndPath(invalidContentType)
    ).toThrowError(ErrorGetFileContentAndPathNoReturn);
  });
});

describe('Success cases', () => {
  describe('Tokens', () => {
    test('It should return valid data for MJS', () => {
      expect(
        // @ts-ignore
        getFileContentAndPath(getFileContentAndPathOperationToken)
      ).toMatchObject({
        fileContent: expectedStandard,
        filePath: 'tokens/colors.mjs'
      });
    });

    test('It should return valid data for TS', () => {
      expect(
        // @ts-ignore
        getFileContentAndPath({ ...getFileContentAndPathOperationToken, format: 'ts' })
      ).toMatchObject({
        fileContent: expectedTs,
        filePath: 'tokens/colors.ts'
      });
    });

    test('It should return valid data for enum', () => {
      const data = {
        ...getFileContentAndPathOperationToken,
        metadata: {
          dataType: 'enum'
        }
      };

      expect(
        // @ts-ignore
        getFileContentAndPath(data)
      ).toMatchObject({
        fileContent: expectedEnum,
        filePath: 'tokens/colors'
      });
    });

    test('It should return valid data for CSS variables', () => {
      expect(
        // @ts-ignore
        getFileContentAndPath({ ...getFileContentAndPathOperationToken, format: 'css' })
      ).toMatchObject({
        fileContent: expectedCss,
        filePath: 'tokens/colors.css'
      });
    });

    test('It should return valid data for SCSS variables', () => {
      expect(
        // @ts-ignore
        getFileContentAndPath({ ...getFileContentAndPathOperationToken, format: 'scss' })
      ).toMatchObject({
        fileContent: expectedScss,
        filePath: 'tokens/_colors.scss'
      });
    });
  });

  describe('Components', () => {
    // TODO: Test fails inexplicably on Windows?
    test('It should return valid data for components', () => {
      const fileContent = `import React from 'react';
import PropTypes from 'prop-types';

import colorsStyled from './colorsStyled';

const colors = (props) => <colorsStyled {...props}>{props.children ? props.children : \"text\"}</colorsStyled>;

colors.propTypes = {};

export default colors;`;

      expect(
        // @ts-ignore
        getFileContentAndPath(getFileContentAndPathOperationComponent)
      ).toMatchObject({
        fileContent: fileContent,
        filePath: 'tokens/colors.mjs'
      });
    });
  });

  describe('Style', () => {
    test('It should return valid data for style', () => {
      const fileContent = `import styled from 'styled-components';

import ColorsCss from './ColorsCss';

// Extend the below as needed
const ColorsStyled = styled.div\`
  \${ColorsCss};
\`;

export default ColorsStyled;`;

      expect(
        // @ts-ignore
        getFileContentAndPath(getFileContentAndPathOperationStyle)
      ).toMatchObject({
        fileContent: fileContent,
        filePath: 'tokens/colorsStyled.mjs'
      });
    });
  });

  describe('CSS', () => {
    test('It should return valid data for CSS', () => {
      const fileContent = `// THIS FILE IS AUTO-GENERATED BY FIGMAGIC. DO NOT MAKE EDITS IN THIS FILE! CHANGES WILL GET OVER-WRITTEN BY ANY FURTHER PROCESSING.
\n
const colorsCss = \`[object Object]\`;

export default colorsCss;`;

      expect(
        // @ts-ignore
        getFileContentAndPath(getFileContentAndPathOperationCss)
      ).toMatchObject({
        fileContent: fileContent,
        filePath: 'tokens/colorsCss.mjs'
      });
    });
  });

  describe('Story', () => {
    test('It should return valid data for Storybook', () => {
      const fileContent = `import React from 'react';
import colors from './colors';

import notes from './colors.description.md';

export default { title: 'colors', parameters: { notes } };

export const colorsRegular = () => <colors>text</colors>;`;

      expect(
        // @ts-ignore
        getFileContentAndPath(getFileContentAndPathOperationStory)
      ).toMatchObject({
        fileContent: fileContent,
        filePath: 'tokens/colors.stories.js'
      });
    });
  });

  describe('Description', () => {
    test('It should return valid data for description', () => {
      const fileContent = `<!--THIS FILE IS AUTO-GENERATED BY FIGMAGIC. DO NOT MAKE EDITS IN THIS FILE! CHANGES WILL GET OVER-WRITTEN BY ANY FURTHER PROCESSING.-->
[object Object]`;

      expect(
        // @ts-ignore
        getFileContentAndPath(getFileContentAndPathOperationDescription)
      ).toMatchObject({
        fileContent: fileContent,
        filePath: 'tokens/colors.description.mjs'
      });
    });
  });
});
